/*
 * Copyright (C) 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.megagoodsoftware.MediaShare;

import java.util.HashMap;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.widget.AdapterView;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.megagoodsoftware.smugmug.Constants;
import com.megagoodsoftware.smugmug.SmugMug;
import com.megagoodsoftware.smugmug.SmugMugAccount;
import com.megagoodsoftware.smugmug.exceptions.SmugMugBadAuthentication;
import com.megagoodsoftware.smugmug.exceptions.SmugMugFailedResponse;
import com.megagoodsoftware.smugmug.exceptions.SmugMugInternalError;

/**
 * Activity used to login the user. The activity asks for the user name and then add
 * the user to the users list upong successful login. If the login is unsuccessful,
 * an error message is displayed. Clicking any stored user launches PhotostreamActivity.
 *
 * This activity is also used to create Home shortcuts. When the intent
 * {@link Intent#ACTION_CREATE_SHORTCUT} is used to start this activity, sucessful login
 * returns a shortcut Intent to Home instead of proceeding to PhotostreamActivity.
 *
 * The shortcut Intent contains the real name of the user, his buddy icon, the action
 * {@link android.content.Intent#ACTION_VIEW} and the URI flickr://photos/nsid.
 */
public class LoginActivity extends Activity implements AdapterView.OnItemClickListener {

    private static final int MENU_ID_SHOW = 1;
    private static final int MENU_ID_DELETE = 2;
	private static final int GET_LOGIN_CREDENTIALS = 3;

    private boolean mCreateShortcut;

    private TextView mUsername;
    private ProgressBar mProgress;
    private TextView mPassword;
    private SQLiteDatabase mDatabase;
    private UsersAdapter mAdapter;

    private AsyncTask<?, ?, ?> mTask;

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {

		case 0: {
			ProgressDialog dialog = new ProgressDialog(this);
			dialog.setMessage("Logging in to SmugMug ...");
			dialog.setIndeterminate(true);
			dialog.setCancelable(true);
			return dialog;
		}
        case GET_LOGIN_CREDENTIALS:
            LayoutInflater factory = LayoutInflater.from(this); 
            final View textEntryView = factory.inflate(R.layout.alert_dialog_text_entry, null);
            return new AlertDialog.Builder(LoginActivity.this)
                .setIcon(R.drawable.alert_dialog_icon)
                .setTitle(R.string.new_login_text)
                .setView(textEntryView)
                .setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                      mUsername = (TextView) textEntryView.findViewById(R.id.username_edit);
                      mPassword = (TextView) textEntryView.findViewById(R.id.password_edit);
                      onAddUser(mUsername.getText().toString(), mPassword.getText().toString());
                    }
                })
                .setNegativeButton(R.string.alert_dialog_cancel, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {

                        /* User clicked cancel so do some stuff */
                    }
                }).create();
            }
        return null;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
    	super.onCreate(savedInstanceState);

        schedule();
        // If the activity was started with the "create shortcut" action, we
        // remember this to change the behavior upon successful login
        if (Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction())) {
            mCreateShortcut = true;
        }

        mDatabase = new UserDatabase(this).getWritableDatabase();

        setContentView(R.layout.screen_login);
		CookieSyncManager.createInstance(this);

        setupViews();
        //printPrefs();
        automaticallyLoginIfNecessary();
    }

    private void automaticallyLoginIfNecessary() {
        SharedPreferences mPreferences = getSharedPreferences(Preferences.NAME, MODE_PRIVATE);
        if (mPreferences.getBoolean(Preferences.KEY_AUTOLOGIN, false) && 
        		(mAdapter.getCount() == 1)) {
        	Cursor cursor = mDatabase.query(UserDatabase.TABLE_USERS,
                new String[] { UserDatabase._ID, UserDatabase.COLUMN_REALNAME,
                UserDatabase.COLUMN_NSID, UserDatabase.COLUMN_HASH, UserDatabase.COLUMN_BUDDY_ICON },
                null, null, null, null, UserDatabase.SORT_DEFAULT);

        	cursor.moveToFirst();
        	int nsidColumn = cursor.getColumnIndex(UserDatabase.COLUMN_NSID); 
        	int hashColumn = cursor.getColumnIndex(UserDatabase.COLUMN_HASH);

        	Log.i(Constants.TAG, "LoginActivity: automaticallyLoginIfNecessary(): loginPref: " + 
				mPreferences.getBoolean(Preferences.KEY_AUTOLOGIN, false) + " adapter Count: " +
				mAdapter.getCount()); 
         	//Object foo = mAdapter.getItem(0);
        	final User user = new User(cursor.getString(nsidColumn),
        								cursor.getString(hashColumn));
        	loginAndPickAlbum(user);
        }
	}

    private void schedule() {
        //SharedPreferences preferences = getSharedPreferences(Preferences.NAME, MODE_PRIVATE);
        //if (!preferences.getBoolean(Preferences.KEY_ALARM_SCHEDULED, false)) {
        CheckUpdateService.schedule(this);
        //    preferences.edit().putBoolean(Preferences.KEY_ALARM_SCHEDULED, true).commit();
        //}
    }

    private void setupViews() {
    	Cursor users = initializeCursor();
        mAdapter = new UsersAdapter(this, users);

        final ListView userList = (ListView) findViewById(R.id.list_users);
        userList.setAdapter(mAdapter);
        userList.setOnItemClickListener(this);
        
        registerForContextMenu(userList);

        mProgress = (ProgressBar) findViewById(R.id.progress);
        if (!users.moveToFirst()) {
        	showDialog(GET_LOGIN_CREDENTIALS);
        }
    }

    private Cursor initializeCursor() {
        Cursor cursor = mDatabase.query(UserDatabase.TABLE_USERS,
                new String[] { UserDatabase._ID, UserDatabase.COLUMN_REALNAME,
                UserDatabase.COLUMN_NSID, UserDatabase.COLUMN_HASH, UserDatabase.COLUMN_BUDDY_ICON },
                null, null, null, null, UserDatabase.SORT_DEFAULT);

        startManagingCursor(cursor);

        return cursor;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.login, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_item_settings:
                SettingsActivity.show(this);
                return true;
            case R.id.menu_item_info:
                Eula.showDisclaimer(this);
                return true;
            case R.id.menu_item_add_user:
            	showDialog(GET_LOGIN_CREDENTIALS);
                return true;
        }

        return super.onMenuItemSelected(featureId, item);
    }

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        final User user = new User(((UserDescription) view.getTag()).nsid,((UserDescription) view.getTag()).hash);
        if (!mCreateShortcut) {
        	loginAndPickAlbum(user);
        } else {
            onCreateShortcut(user);
        }
    }

    private void loginAndPickAlbum(User user) {
        mTask = new LoginToSmugMugTask().execute(user);
	}

	@Override
    public void onCreateContextMenu(ContextMenu menu, View v,
            ContextMenu.ContextMenuInfo menuInfo) {

        super.onCreateContextMenu(menu, v, menuInfo);

        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
        menu.setHeaderTitle(((TextView) info.targetView).getText());

        menu.add(0, MENU_ID_SHOW, 0, R.string.context_menu_show_MediaShare);
        menu.add(0, MENU_ID_DELETE, 0, R.string.context_menu_delete_user);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)
                item.getMenuInfo();
        final UserDescription description = (UserDescription) info.targetView.getTag();

        switch (item.getItemId()) {
            case MENU_ID_SHOW:
                final User user = User.fromId(description.nsid);
                onPickAlbum(user);
                return true;
            case MENU_ID_DELETE:
                onRemoveUser(description.id);
                return true;
        }

        return super.onContextItemSelected(item);
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (mProgress.getVisibility() == View.VISIBLE) {
            mProgress.setVisibility(View.GONE);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mTask != null && mTask.getStatus() == AsyncTask.Status.RUNNING) {
            mTask.cancel(true);
        }

        mAdapter.cleanup();
        mDatabase.close();
    }

    private void onAddUser(String username, String password) {
        // When the user enters his user name, we need to find his NSID before
        // adding it to the list.
        mTask = new FindSMUserTask().execute(username, password);
    }

    private void onRemoveUser(String id) {
        int rows = mDatabase.delete(UserDatabase.TABLE_USERS, UserDatabase._ID + "=?",
                new String[] { id });
        if (rows > 0) {
            mAdapter.refresh();
        }
    }

    private void onError() {
        hideProgress();
        mUsername.setError(getString(R.string.screen_login_error));
    	showDialog(GET_LOGIN_CREDENTIALS);
    }

    private void hideProgress() {
        if (mProgress.getVisibility() != View.GONE) {
            final Animation fadeOut = AnimationUtils.loadAnimation(this, R.anim.fade_out);
            mProgress.setVisibility(View.GONE);
            mProgress.startAnimation(fadeOut);
        }
    }

    private void showProgress() {
        if (mProgress.getVisibility() != View.VISIBLE) {
            final Animation fadeIn = AnimationUtils.loadAnimation(this, R.anim.fade_in);
            mProgress.setVisibility(View.VISIBLE);
            mProgress.startAnimation(fadeIn);
        }
    }

    private void onPickAlbum(User user) {
   		PickAlbumActivity.show(this, user);
   		finish();
    }

    /**
     * Creates the shortcut Intent to send back to Home. The intent is a view action
     * to a flickr://photos/nsid URI, with a title (real name or user name) and a
     * custom icon (the user's buddy icon.)
     *
     * @param user The user to create a shortcut for.
     */
    private void onCreateShortcut(User user) {
        final Cursor cursor = mDatabase.query(UserDatabase.TABLE_USERS,
                new String[] { UserDatabase.COLUMN_REALNAME, UserDatabase.COLUMN_USERNAME,
                UserDatabase.COLUMN_BUDDY_ICON }, UserDatabase.COLUMN_NSID + "=?",
                new String[] { user.getId() }, null, null, UserDatabase.SORT_DEFAULT);
        cursor.moveToFirst();

        final Intent shortcutIntent = new Intent(MediaShareActivity.ACTION);
        shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        shortcutIntent.putExtra(MediaShareActivity.EXTRA_NSID, user.getId());

        // Sets the custom shortcut's title to the real name of the user. If no
        // real name was found, use the user name instead.
        final Intent intent = new Intent();
        intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
        String name = cursor.getString(cursor.getColumnIndexOrThrow(UserDatabase.COLUMN_REALNAME));
        if (name == null || name.length() == 0) {
            name = cursor.getString(cursor.getColumnIndexOrThrow(UserDatabase.COLUMN_USERNAME));
        }
        intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);

        // Sets the custom shortcut icon to the user's buddy icon. If no buddy
        // icon was found, use a default local buddy icon instead.
        byte[] data = cursor.getBlob(cursor.getColumnIndexOrThrow(UserDatabase.COLUMN_BUDDY_ICON));
        Bitmap icon = BitmapFactory.decodeByteArray(data, 0, data.length);
        if (icon != null) {
            intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
        } else {
            intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
                    Intent.ShortcutIconResource.fromContext(this, R.drawable.default_buddyicon));
        }

        setResult(RESULT_OK, intent);
        finish();
    }

    private class LoginToSmugMugTask extends AsyncTask<User, Void, User> {
        @Override
        public void onPreExecute() {
			showDialog(0);
        }

        public User doInBackground(User... params) {
        	User mUser = null;
        	try {
    			mUser = params[0];
    			SmugMug sm = ((MediaShareApp) getApplicationContext()).getSmugMugHandle();
    			User lUser = ((MediaShareApp) getApplicationContext()).getLoggedInUser();
    			if ((lUser == null) || ((lUser != null) && (!mUser.getId().equals(lUser.getId())))) {
        			Log.i(Constants.TAG, "Logging in to SmugMug, lUser: " + (lUser == null?"null":lUser.getId()) + " mUser: " + mUser.getId()); 

    				sm.loginWithHash(Integer.parseInt(mUser.getId()), 
    									mUser.getPassword());
    				((MediaShareApp) getApplicationContext()).setLoggedIn(mUser);
    			}
    			Log.i(Constants.TAG, sm.getAccount().toString()); 
    			
    			sm.updateCache();
     		} catch (NumberFormatException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (SmugMugBadAuthentication e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (SmugMugInternalError e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (SmugMugFailedResponse e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    		if (CookieManager.getInstance().hasCookies()) {
    			Log.i(Constants.TAG,"Has cookies!\n");
    		}
    		else {
        		Log.i(Constants.TAG,"Has no cookies!\n");
    		}
    		
    		return mUser;
        }

        @Override
        public void onPostExecute(User user) {
        	dismissDialog(0);
            onPickAlbum(user);

            mTask = null;
        }
    }

    /**
     * Background task used to load the user's NSID. The task begins by showing the
     * progress bar, then loads the user NSID from the network and finally open
     * MediaShareActivity.
     */
    private class FindSMUserTask extends AsyncTask<String, Void, User> {
        @Override
        public void onPreExecute() {
            showProgress();
        }

        public User doInBackground(String... params) {
            final String name = params[0].trim();
            final String password = params[1].trim();
            if (name.length() == 0) return null;
			long result = -1;
			final User user;
			
 //           SmugMug sm;
			SmugMug sm = ((MediaShareApp) getApplicationContext()).getSmugMugHandle();
			try {
				sm.loginWithPassword(name, password);
	    		if (CookieManager.getInstance().hasCookies()) {
	    			Log.i(Constants.TAG,"Has cookies!\n");
	    		}
	    		else {
	        		Log.i(Constants.TAG,"Has no cookies!\n");
	    		}

				SmugMugAccount sma = sm.getAccount();

				user = new User(Integer.toString(sma.getUserId()), sma.getPassword());

				
				if (isCancelled() || user == null) return null;
				((MediaShareApp) getApplicationContext()).setLoggedIn(user);

				final ContentValues values = new ContentValues();
				values.put(UserDatabase.COLUMN_USERNAME, name);
				values.put(UserDatabase.COLUMN_REALNAME, sma.getNickName());
				values.put(UserDatabase.COLUMN_NSID, user.getId());
				values.put(UserDatabase.COLUMN_HASH, user.getPassword());
				values.put(UserDatabase.COLUMN_LAST_UPDATE, System.currentTimeMillis());

				final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.smugmug);
				UserDatabase.writeBitmap(values, UserDatabase.COLUMN_BUDDY_ICON, bitmap);

				if (!isCancelled()) {
					result = mDatabase.insert(UserDatabase.TABLE_USERS,
							UserDatabase.COLUMN_REALNAME, values);
				}
				return result != -1 ? user : null;
				
			} catch (SmugMugBadAuthentication e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SmugMugInternalError e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 

			return null;
        }

        @Override
        public void onPostExecute(User user) {
            if (user == null) {
                onError();
            } else {
                mAdapter.refresh();
                hideProgress();
            }
        }
    }

    private class UsersAdapter extends CursorAdapter {
        private final LayoutInflater mInflater;
        private final int mRealname;
        private final int mId;
        private final int mNsid;
        private final int mBuddyIcon;
        private final int mHash;
        
        private final Drawable mDefaultIcon;
        private final HashMap<String, Drawable> mIcons = new HashMap<String, Drawable>();

        public UsersAdapter(Context context, Cursor cursor) {
            super(context, cursor, true);

            mInflater = LayoutInflater.from(context);
            mDefaultIcon = context.getResources().getDrawable(R.drawable.default_buddyicon);

            mRealname = cursor.getColumnIndexOrThrow(UserDatabase.COLUMN_REALNAME);
            mId = cursor.getColumnIndexOrThrow(UserDatabase._ID);
            mNsid = cursor.getColumnIndexOrThrow(UserDatabase.COLUMN_NSID);
            mHash = cursor.getColumnIndexOrThrow(UserDatabase.COLUMN_HASH);
            mBuddyIcon = cursor.getColumnIndexOrThrow(UserDatabase.COLUMN_BUDDY_ICON);
            //mHash = cursor.getColumnIndexOrThrow(UserDatabase.COLUMN_HASH);
        }

        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            final View view = mInflater.inflate(R.layout.list_item_user, parent, false);
            final UserDescription description = new UserDescription();
            view.setTag(description);
            return view;
        }

        public void bindView(View view, Context context, Cursor cursor) {
            final UserDescription description = (UserDescription) view.getTag();
            description.id = cursor.getString(mId);
            description.nsid = cursor.getString(mNsid);
            description.hash = cursor.getString(mHash);

            final TextView textView = (TextView) view;
            textView.setText(cursor.getString(mRealname));

            Drawable icon = mIcons.get(description.nsid);
            if (icon == null) {
                final byte[] data = cursor.getBlob(mBuddyIcon);

                Bitmap bitmap = null;
                if (data != null) bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

                if (bitmap != null) {
                    icon = new FastBitmapDrawable(bitmap);
                } else {
                    icon = mDefaultIcon;
                }

                mIcons.put(description.nsid, icon);
            }

            textView.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
        }

        void cleanup() {
            for (Drawable icon : mIcons.values()) {
                icon.setCallback(null);
            }
        }

        void refresh() {
            getCursor().requery();
        }
    }

    private static class UserDescription {
        String id;
        String nsid;
        String hash;
    }
}
